package com.alipay.sofa.award.endpoint.filter;

import com.alipay.sofa.award.biz.service.config.AwardConfigurationProperties;
import com.alipay.sofa.award.biz.service.model.QpsControlModel;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.container.*;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * WinAwardFilter
 *
 * @author yangguanchao
 * @since 2018/09/08
 */
@Provider
@PreMatching
public class WinAwardFilter implements ContainerRequestFilter, ContainerResponseFilter {

    private AwardConfigurationProperties awardConfigurationProperties = null;

    private QpsControlModel              qpsControlModel              = null;

    @Autowired
    public WinAwardFilter(AwardConfigurationProperties awardConfigurationProperties) {
        this.awardConfigurationProperties = awardConfigurationProperties;
        this.qpsControlModel = new QpsControlModel(
            this.awardConfigurationProperties.getQpsLimitCount(),
            this.awardConfigurationProperties.getQpsPeriodMills(), TimeUnit.MILLISECONDS);
    }

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        if (this.skipFilter(requestContext)) {
            return;
        }
        //qps limit
        if (!this.qpsControlModel.canPass()) {
            throw new RuntimeException("Flow beyond the limit, QpsLimitCount = ["
                                       + this.awardConfigurationProperties.getQpsLimitCount()
                                       + "] and " + "QpsPeriodMills = ["
                                       + this.awardConfigurationProperties.getQpsPeriodMills()
                                       + "]");
        }
    }

    private boolean skipFilter(ContainerRequestContext ctx) {
        //only limit get award facade
        String uriPath = ctx.getUriInfo().getPath();
        List<String> qpsLimitedUriPahList = this.awardConfigurationProperties
            .getQpsLimitedUriPahList();
        if (qpsLimitedUriPahList == null || qpsLimitedUriPahList.size() <= 0) {
            return true;
        }
        for (String qpsLimitedUriPah : qpsLimitedUriPahList) {
            if (uriPath.equalsIgnoreCase(qpsLimitedUriPah)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void filter(ContainerRequestContext requestContext,
                       ContainerResponseContext responseContext) throws IOException {
        //nothing
    }
}
